package com.kaili.basic.service.impl;

import com.baomidou.mybatisplus.plugins.Page;
import com.kaili.basic.mapper.DeviceMapper;
import com.kaili.basic.mapper.AlarmMapper;
import com.kaili.basic.mapper.AlarmSetMapper;
import com.kaili.basic.mapper.DeviceOnlineMapper;
import com.kaili.basic.pojo.dto.MdmDeviceOnlineAddDto;
import com.kaili.basic.pojo.dto.MdmDeviceOnlineQueryDto;
import com.kaili.basic.pojo.dto.MdmDeviceOnlineUpdateDto;
import com.kaili.basic.pojo.entity.*;
import com.kaili.basic.pojo.vo.MdmAlarmSetVo;
import com.kaili.basic.pojo.vo.MdmDeviceOnlineDetailVo;
import com.kaili.basic.pojo.vo.MdmDeviceOnlineListVo;
import com.kaili.basic.service.IMdmDeviceOnlineService;
import com.kaili.common.response.CommonStatus;
import com.kaili.common.response.RestStatus;
import com.kaili.common.util.CommonUtil;
import com.kaili.common.util.LoginDetailUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Description:
 * @Author: shenliqiang
 * @CreateDate: 2019/7/24 11:19
 * @Version: 1.0
 */
@Service
@Transactional
public class DeviceOnlineServiceImpl implements IMdmDeviceOnlineService {

    @Autowired
    DeviceOnlineMapper deviceOnlineMapper;

    @Autowired
    DeviceMapper deviceMapper;

    @Autowired
    AlarmSetMapper mdmAlarmSetMapper;

    @Autowired
    AlarmMapper mdmAlarmMapper;

    @Autowired
    private MessageSource messageSource;

    /**
     * @Desc:  创建设备时调用此方法创建设备
     * @author: shenliqiang
     * @Time: 2019/7/30 10:44
     * @param dto
     * @return int
     */

    @Override
    public RestStatus addMdmDeviceOnline(MdmDeviceOnlineAddDto dto) {
        MdmDeviceOnline mdmDeviceOnline = new MdmDeviceOnline();
        BeanUtils.copyProperties(dto, mdmDeviceOnline);
        mdmDeviceOnline.setCreateBy(LoginDetailUtils.getCurrent().getId());
        deviceOnlineMapper.addMdmDeviceOnline(mdmDeviceOnline);
        return CommonStatus.ADD_OK;
    }
    /**
     * @Desc:  删除设备时调用此接口删除设备
     * @author: shenliqiang
     * @Time: 2019/7/30 10:44
     * @param deviceIds
     * @return int
     */

    @Override
    public RestStatus deleteMdmDeviceOnlines(Long[] deviceIds) {
        Map<String,Object> map = new HashMap<>();
        map.put("modifyBy", LoginDetailUtils.getCurrent().getId());
        map.put("deviceIds",deviceIds);
        deviceOnlineMapper.deleteMdmDeviceOnlines(map);
        return CommonStatus.DELETE_OK;
    }

    /**
     * @Desc:  更新设备在线状态--设备
     * @author: shenliqiang
     * @Time: 2019/7/30 10:45
     * @param dto
     * @return int
     */

    @Override
    public void updateMdmDeviceOnline(MdmDeviceOnlineUpdateDto dto) {

        List<MdmAlarmSetVo> lists  = this.mdmAlarmSetMapper.queryList();
        for (MdmAlarmSetVo list:lists) {
            if(list.getAlarmName().equals("低版本")){
                //1低版本,上传版本号且低版本告警已开启
                if(dto.getRomVersion()!=null){
                    String content ="";
                    int versionResult = compareVersion(list.getRomVcontent(),dto.getRomVersion());
                    if(versionResult==1){ //版本告警
                        content += CommonUtil.getMessage(messageSource,"theDeviceRomVersionIs")+dto.getRomVersion()+","+CommonUtil.getMessage(messageSource,"isLowerThanWarnVersion")+"："+list.getRomVcontent();
                    }
                    int assistantResult = compareVersion(list.getAideContent(),dto.getAssistantVersion());
                    if(assistantResult==1){ //assistant告警
                        content += CommonUtil.getMessage(messageSource,"theAssistantVersionIs")+dto.getRomVersion()+","+CommonUtil.getMessage(messageSource,"isLowerThanWarnVersion")+"："+list.getAideContent();
                    }
                    //查询数据库中是否有低版本告警记录
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String,Object>(){{
                        this.put("deviceId",dto.getFacilityId());
                        this.put("alarmId",1);
                    }});
                    if(!content.equals("")) {
                        if(entity==null||entity.getCloseTime()!=null){//没有该设备记录或者无生效告警记录则直接新增
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 1, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }else if(!entity.getContent().equals(content)){//如果已存在相同记录则不新增
                            //如果于之前记录不一致则新增记录，原纪录关闭
                            //关闭原纪录
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(),Calendar.getInstance().getTime(),LoginDetailUtils.getCurrent().getId(),Calendar.getInstance().getTime()));
                            //新增记录
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 1, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    }else{//关闭记录
                        if(entity!=null&&entity.getCloseTime()==null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(),Calendar.getInstance().getTime(),LoginDetailUtils.getCurrent().getId(),Calendar.getInstance().getTime()));
                    }
                }
            }
            if(list.getAlarmName().equals("低电量")){
                if(dto.getBatteryp()!=null){
                    Double alarmPower = Double.valueOf(list.getRomVcontent());
                    Double devicePower = dto.getBatteryp().doubleValue();
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String,Object>(){{
                        this.put("deviceId",dto.getFacilityId());
                        this.put("alarmId",2);
                    }});
                    if(devicePower<alarmPower){
                        String content = CommonUtil.getMessage(messageSource,"thePowerOfTheDeviceIs")+devicePower+"%,"+CommonUtil.getMessage(messageSource,"isLowerThanWarnVersion")+"："+alarmPower+"%";
                        if(entity==null||entity.getCloseTime()!=null){
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 2, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    }else{
                        if(entity!=null&&entity.getCloseTime()==null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(),Calendar.getInstance().getTime(),LoginDetailUtils.getCurrent().getId(),Calendar.getInstance().getTime()));
                    }
                }
            }
            if(list.getAlarmName().equals("低内存")) {
                //3低内存
                if (dto.getMemoryUsed() != null) {
                    double alarmMemoryUsed = Double.valueOf(list.getRomVcontent());
                    double deviceMemoryUsed = dto.getMemoryUsed().doubleValue();
                    MdmDeviceOnline MdmDeviceOnline = this.deviceOnlineMapper.queryOnlineDeviceById(
                            this.deviceMapper.getDeviceByImei(dto.getImei()).getId()
                    );
                    double memoryUsed = (MdmDeviceOnline.getMemoryAll().doubleValue() - deviceMemoryUsed) / MdmDeviceOnline.getMemoryAll().doubleValue();
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String, Object>() {{
                        this.put("deviceId", dto.getFacilityId());
                        this.put("alarmId", 3);
                    }});
                    if (memoryUsed < alarmMemoryUsed / 100d) {
                        String content = CommonUtil.getMessage(messageSource, "theDeviceIsOutOfMemory") + (int) (memoryUsed * 100) + "%," + CommonUtil.getMessage(messageSource, "isLowerThanWarnVersion") + "：" + alarmMemoryUsed + "%";
                        if (entity == null || entity.getCloseTime() != null) {//没有该设备记录或者无生效告警记录则直接新增
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 3, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    } else {
                        if (entity != null && entity.getCloseTime() == null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(), Calendar.getInstance().getTime(), LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                    }
                }
            }
            if(list.getAlarmName().equals("高CPU")) {
                //4高CPU
                if (dto.getCpuUsage() != null) {
                    double alarmCpuUsage = Double.valueOf(list.getRomVcontent());
                    double deviceCpuUsage = dto.getCpuUsage().doubleValue();
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String, Object>() {{
                        this.put("deviceId", dto.getFacilityId());
                        this.put("alarmId", 4);
                    }});
                    if (deviceCpuUsage > alarmCpuUsage) {
                        String content = CommonUtil.getMessage(messageSource, "TheDeviceCurrentlyHasCPUUtilizationOf") + deviceCpuUsage + "%," + CommonUtil.getMessage(messageSource, "isHighThanWarnVersion") + "：" + alarmCpuUsage + "%";
                        if (entity == null || entity.getCloseTime() != null) {//没有该设备记录或者无生效告警记录则直接新增
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 4, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    } else {
                        if (entity != null && entity.getCloseTime() == null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(), Calendar.getInstance().getTime(), LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                    }
                }
            }

            if(list.getAlarmName().equals("SIM卡变更")) {
                //6SIM卡变更
                if (dto.getIsSimChanged() != null) {
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String, Object>() {{
                        this.put("deviceId", dto.getFacilityId());
                        this.put("alarmId", 6);
                    }});
                    if (dto.getIsSimChanged() == 1) {
                        String content = CommonUtil.getMessage(messageSource, "TheSimCardHasBeenChangedInThisDevice");
                        if (entity == null || entity.getCloseTime() != null) {
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 6, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    } else {
                        if (entity != null && entity.getCloseTime() == null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(), Calendar.getInstance().getTime(), LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                    }
                }
            }
            if(list.getAlarmName().equals("SD卡变更")) {
                //7SD卡变更
                if (dto.getSdChanged() != null) {
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String, Object>() {{
                        this.put("deviceId", dto.getFacilityId());
                        this.put("alarmId", 7);
                    }});
                    if (dto.getSdChanged() == 1) {
                        String content = CommonUtil.getMessage(messageSource, "TheDeviceHasBeenChangedWithSdCard");
                        if (entity == null || entity.getCloseTime() != null) {
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 7, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    } else {
                        if (entity != null && entity.getCloseTime() == null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(), Calendar.getInstance().getTime(), LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                    }
                }
            }
            if(list.getAlarmName().equals("越狱/ROOT")) {
                //8越狱/ROOT
                if (dto.getIsCrack() != null) {
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String, Object>() {{
                        this.put("deviceId", dto.getFacilityId());
                        this.put("alarmId", 8);
                    }});
                    if (dto.getIsCrack() == 1) {
                        String content = CommonUtil.getMessage(messageSource, "TheDeviceHasBeenJailbroken");
                        if (entity == null || entity.getCloseTime() != null) {
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 8, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    } else {
                        if (entity != null && entity.getCloseTime() == null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(), Calendar.getInstance().getTime(), LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                    }
                }
            }
            if(list.getAlarmName().equals("非法关机")) {
                //9非法关机
                if (dto.getIsIllegalTerminate() != null) {
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String, Object>() {{
                        this.put("deviceId", dto.getFacilityId());
                        this.put("alarmId", 9);
                    }});
                    if (dto.getIsIllegalTerminate() == 1) {
                        String content = CommonUtil.getMessage(messageSource, "AnIllegalShutdownOccurredOnTheDevice");
                        if (entity == null || entity.getCloseTime() != null) {
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 9, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    } else {
                        if (entity != null && entity.getCloseTime() == null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(), Calendar.getInstance().getTime(), LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                    }
                }
            }
            if(list.getAlarmName().equals("超使用范围")) {
                //10超使用范围--finish
                if (dto.getLatitude() != null) {
                    double la1 = new BigDecimal(dto.getLatitude()).doubleValue();
                    double lo1 = new BigDecimal(dto.getLongitude()).doubleValue();
                    double radius = list.getRadius().doubleValue();
                    double la2 = list.getLatitude().doubleValue();
                    double lo2 = list.getLongitude().doubleValue();
                    double result = calDistance(lo1, la1, lo2, la2);
                    MdmAlarmEntity entity = this.mdmAlarmMapper.queryLatestRecordByDeviceId(new HashMap<String, Object>() {{
                        this.put("deviceId", dto.getFacilityId());
                        this.put("alarmId", 10);
                    }});
                    if (result > radius * 1000) {
                        String content = CommonUtil.getMessage(messageSource, "TheDeviceHasBeenOverusedAndTheLocationOfTheDeviceIs") + "：" + lo1 + "," + la1 + "," + CommonUtil.getMessage(messageSource, "TheDistanceFromTheCenterIs") + ((((double) (int) (result)) / 1000)) + "KM";
                        if (entity == null || entity.getCloseTime() != null) {
                            this.mdmAlarmMapper.insert(new MdmAlarmEntity(dto.getFacilityId().intValue(), content, 10, "1", LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                        }
                    } else {
                        if (entity != null && entity.getCloseTime() == null)
                            this.mdmAlarmMapper.updateById(new MdmAlarmEntity(entity.getId(), Calendar.getInstance().getTime(), LoginDetailUtils.getCurrent().getId(), Calendar.getInstance().getTime()));
                    }
                }
            }
        }
    }
    /**
     * @Desc:  计算经纬度距离
     * @author: shenliqiang
     * @Time: 2019/7/30 10:45
     * @param la1
     * @param lo1
     * @param la2
     * @param lo2
     * @return double
     */
    //地球半径
    private static final double EARTH_RADIUS = 6378137.0D;
    /**
     * 计算两点距离
     * @param startLon 起点经度
     * @param startLat 起点纬度
     * @param endLon 终点经度
     * @param endLat 终点纬度
     * @return  单位米
     */
    public static double calDistance(double startLon, double startLat, double endLon, double endLat) {
        double lat1 = toRadians(startLat);
        double lat2 = toRadians(endLat);
        double deltaLatBy2 = (lat2 - lat1) / 2.0D;
        double deltaLonBy2 = toRadians(endLon - startLon) / 2.0D;
        double a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) + Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) * Math.cos(lat1) * Math.cos(lat2);
        return EARTH_RADIUS * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1.0D - a));
    }
    /**
     * 度转弧度
     * @param angleInDegrees
     * @return
     */
    static double toRadians(double angleInDegrees) {
        return angleInDegrees * 3.141592653589793D / 180.0D;
    }

    /**
     * @Desc:  分页查询
     * @author: shenliqiang
     * @Time: 2019/7/30 10:45
     * @param page
     * @param mdmDeviceOnlineQueryDto
     * @return com.baomidou.mybatisplus.plugins.Page<com.kaili.basic.pojo.vo.MdmDeviceOnlineVo>
     */

    @Override
    public Page<MdmDeviceOnlineListVo> queryMdmDeviceOnline(Page<MdmDeviceOnlineListVo> page, MdmDeviceOnlineQueryDto mdmDeviceOnlineQueryDto) {
        List<MdmDeviceOnlineListVo> mdmDeviceOnlines = deviceOnlineMapper.queryMdmDevice(page,mdmDeviceOnlineQueryDto);
        return page.setRecords(mdmDeviceOnlines);
    }

    /**
     * @Desc:  导出操作
     * @author: shenliqiang
     * @Time: 2019/7/30 10:46
     * @param mdmDeviceOnlineQueryDto
     * @return java.util.List<com.kaili.basic.pojo.entity.MdmDeviceOnlineExport>
     */

    @Override
    public List<MdmDeviceOnlineExport> queryMdmDeviceOnlineExport(MdmDeviceOnlineQueryDto mdmDeviceOnlineQueryDto) {
        return deviceOnlineMapper.queryMdmDeviceOnlineExport(mdmDeviceOnlineQueryDto);
    }

    /**
     * @Desc:  查看设备详细信息
     * @author: shenliqiang
     * @Time: 2019/7/30 10:46
     * @param deviceOnlineId
     * @return com.kaili.basic.pojo.vo.MdmDeviceOnlineDetailVo
     */

    @Override
    public MdmDeviceOnlineDetailVo queryOnlineDeviceDetail(Long deviceOnlineId) {
        MdmDeviceOnlineDetailVo vo = deviceOnlineMapper.queryOnlineDeviceDetail(deviceOnlineId);
        MdmDeviceEntity entity = this.deviceMapper.getDeviceByImei(vo.getImei());
        List<MdmAlarmEntity> mdmAlarmEntities = this.mdmAlarmMapper.queryLatestRecordsByDeviceId(entity.getId());
        for (MdmAlarmEntity mdmAlarmEntity:mdmAlarmEntities) {
            if(mdmAlarmEntity.getAlarmSetId()==1){
                if(mdmAlarmEntity.getContent().contains("Rom"))
                    vo.setLowRomVersionWarn(1);
                if(mdmAlarmEntity.getContent().contains(CommonUtil.getMessage(messageSource,"assistant")))
                    vo.setLowAssiVersionWarn(1);
            }
            if(mdmAlarmEntity.getAlarmSetId()==2)
                vo.setLowPowerWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==3)
                vo.setLowMemoryWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==4)
                vo.setHighCpuWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==5)
                vo.setIsOffLineWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==6)
                vo.setIsSimChangedWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==7)
                vo.setIsSDChangedWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==8)
                vo.setIsRootWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==9)
                vo.setIsIllegalTerminateWarn(1);
            if(mdmAlarmEntity.getAlarmSetId()==10)
                vo.setIsOutOfGeofenceWarn(1);
        }
        return vo;
    }

    public static int compareVersion(String v1, String v2) {
        if (v1.equals(v2)) {
            return 0;
        }
        String[] version1Array = v1.split("[._]");
        String[] version2Array = v2.split("[._]");
        int index = 0;
        int minLen = Math.min(version1Array.length, version2Array.length);
        long diff = 0;

        while (index < minLen
                && (diff = Long.parseLong(version1Array[index])
                - Long.parseLong(version2Array[index])) == 0) {
            index++;
        }
        if (diff == 0) {
            for (int i = index; i < version1Array.length; i++) {
                if (Long.parseLong(version1Array[i]) > 0) {
                    return 1;
                }
            }

            for (int i = index; i < version2Array.length; i++) {
                if (Long.parseLong(version2Array[i]) > 0) {
                    return -1;
                }
            }
            return 0;
        } else {
            return diff > 0 ? 1 : -1;
        }
    }
}
